﻿#ifndef __INC_QG_OGL_DEV_H__
#define __INC_QG_OGL_DEV_H__

#ifdef _MSC_VER
#pragma once
#endif

#include "qg/qgasv.h"

#if _SB_WINDOWS_
#	include <GL/gl.h>
#	include "glext/glext.h"
#	include "glext/wglext.h"
#elif _SB_APPLE_
#	include <OpenGL/gl.h>
#	include "glext/glext.h"
#else
#	include <GL/gl.h>
#	include <GL/glx.h>
#	include <GL/glext.h>
#	include <GL/glxext.h>
#endif

//////////////////////////////////////////////////////////////////////////
// OPENGL 디바이스

// 
class GLDevice : public qgDevice
{
	KCH_SUBCLASS(GLDevice, qgDevice);
	KT_DECL_TYPE_INIT(GLDevice);
	KT_DECL_TYPE_FINAL(GLDevice);
	KCH_FRIEND(GLTexture);
	KCH_FRIEND(GLProgram);
	KCH_FRIEND(GLProgramWorker);

public:
	struct Prsn : public qgDevPrsn
	{
		kint					m_tex_active;						// 현재 활성 중인 텍스쳐 스테이지
		GLenum					m_tex_type[QGSGTEX_MAX_VALUE];		// 해당 텍스쳐 활성화 됨? + 해당 텍스쳐 타입
		qgRaszData				m_rasz_data;						// 래스터라이저 대조군
		qgBlndData				m_blnd_data;						// 블렌드 대조군
		bool					m_blnd_blend;						// 블랜드 켜짐 상태
		bool					m_blnd_alpha;						// 블렌드 알파 켜짐 상태

		kint					ws_client[8];						// 레이아웃 클라이언트 스테이트
		kint					ws_custom[8];						// 레이아웃 세이더 스테이트

		qgRenderMode			r_mode;
		kint					r_ortho_tex_attr;					// 0=없음, 1=채움, 2=알파
	};

	struct Debz : public qgDevDebz
	{
	};

	struct Plane
	{
		bool					enable;
		tpl::Plane				plane;
	};

private:
	Prsn				_vprn;
	Debz				_vdeb;
	Plane*				_plns;

private:
#if _SB_WINDOWS_ && !_QG_USE_SDL
	HDC						_hdc;
	HGLRC					_hrc;
	PIXELFORMATDESCRIPTOR	_pfd;
#elif _SB_APPLE_
#error fix me
#elif !_QG_USE_SDL
	GLXDrawable				_drawable;
	Display*				_display;
#endif

private:
	GLDevice();
	~GLDevice();

public:
	K_OVR bool Layout(const qgSevLayout& e);

	K_OVR bool Enter(kint clearance);
	K_OVR bool Leave();
	K_OVR bool Flush();

	K_OVR bool SetTM(qgTmType tm, const tpl::Mat4& m);

	K_OVR void Draw(kint vertexcount, kint vertexstart);
	K_OVR void DrawIndexed(kint indexcount, kint vertexstart);

	K_OVR void DrawRect(const tpl::Rect&bound, const tpl::ColorValue& color, qgTexture* tex, const tpl::Quad* coord);
	K_OVR void DrawGlyph(const tpl::Rect&bound, const tpl::ColorValue& color, qgTexture* tex);
	K_OVR void DrawPolyLine(kint count, const tpl::Point pts[], const tpl::ColorValue colors[]);
	K_OVR void DrawPolyStrip(kint count, const tpl::Point* pts, const tpl::ColorValue* colors, qgTexture* tex, const tpl::Vec2* coords);

	K_OVR qgImage* ScreenCapture();

	K_OVR bool _SetRenderTarget(qgTexture* tex);

protected:
	K_OVR bool _Initialize(qgStub* stub, kint flags);
	K_OVR bool _ResetPrepare(const tpl::Point& size, bool prepare);
	K_OVR void _Finalize();

	K_OVR qgBuffer* _RoamImplBuffer(const qgArprBuffer& arpr);
	K_OVR qgLayout* _RoamImplLayout(qgLayoutData* data);
	K_OVR qgTexture* _RoamImplTexture(const qgArprTexture& arpr);
	K_OVR qgTexture* _RoamImplTexture(const qgArprImage& arpr);
	K_OVR qgTexture* _RoamImplMotionTexture(const char* filename, kint flags);
	K_OVR qgDepthBuffer* _RoamImplDepthBuffer(const tpl::Point& size);
	K_OVR qgShader* _RoamImplShader(const char* name);
	K_OVR qgRasz* _RoamImplRasz(const qgRaszData& data);
	K_OVR qgBlnd* _RoamImplBlnd(const qgBlndData& data);
	K_OVR qgSplr* _RoamImplSplr(const qgSplrData& data);

public:
	GLenum _GetError(const char** str = NULL, bool output = false) throw();

	void _RenderScene() throw();
	void _RenderOrtho(qgTexture* tex, bool hasalpha, bool haschannel, bool glyph) throw();

	bool _SetClipPlane(kint nth, const tpl::Plane& plane, bool enable) throw();
	void _TurnClipPlane(kint nth, bool enable) throw();
	void _UpdateClipPlane(kint nth) throw();

	void _ClearDevice(kint clearance, const tpl::Color& color, kint stencil, float depth) throw();

	bool _ActiveTexture(kint stage) throw();
	bool _CommitTexture(kint stage, qgTexture* tex) throw();
	void _CommitSampler(kint stage, const qgSplrData& nsp, qgSplrData& psp) throw();
	void _CommitRasterize(const qgRaszData& nrz, qgRaszData& prz) throw();
	void _CommitBlendState(const qgBlndData& nbd, qgBlndData& pbd) throw();
	bool _CommitShader() throw();
	bool _CommitLayout(kint stride, kint count, kpointer elmsptr) throw();

	bool _BindMtrl(ksize_t count = QGSGTEX_MAX_VALUE) throw();
	bool _BindShader() throw();
	bool _BindDraw() throw();
	bool _UnbindDraw() throw();
};

#endif	// __INC_QG_OGL_DEV_H__
